package com.loe.logger

import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.util.Log
import com.loe.logger.db.LoggerIdTimeDb
import com.loe.logger.db.LoggerSharedManager
import com.loe.logger.util.LoeLog
import org.json.JSONArray
import org.json.JSONObject

/**
 * Logger管理器
 *
 * @author Administrator
 * @since 2020/7/10-16:52
 */
object LoeLogger
{
    private var db: LoggerIdTimeDb? = null
    private var dbNet: LoggerIdTimeDb? = null

    private var isRelease = true

    fun init(app: Application, isRelease: Boolean)
    {
        this.isRelease = isRelease
        if (!isRelease)
        {
            db = LoggerIdTimeDb(app, "appLogger")
            dbNet = LoggerIdTimeDb(app, "appLoggerNet")
        }
        LoggerSharedManager.init(app)
        staticServeEnvironmentList.clear()
    }

    /**
     * 跳转日志界面
     */
    fun toLogger(context: Context)
    {
        if (db != null) context.startActivity(Intent(context, LoggerActivity::class.java).addFlags(FLAG_ACTIVITY_NEW_TASK))
    }

    /****************************************** net *****************************************/

    public var lastNetTime = 0L
        private set

    /**
     * log网络请求
     */
    fun net(url: String, params: String, result: String)
    {
        net(url, params, "", result)
    }

    fun net(url: String, params: String, headers: String, result: String)
    {
        if (dbNet != null)
        {
            dbNet?.insert(
                JSONObject()
                    .put("url", url)
                    .put("params", params)
                    .put("headers", headers)
                    .put("result", result)
            )
            // log
            var linkInfo = "url：$url\n"
            if (headers.isNotBlank()) linkInfo = linkInfo + "headers：" + headers.replace("\n", " ") + "\n"
            if( params.isNotBlank()) linkInfo = linkInfo + "params：" + params.replace("\n", " ") +
                "\n──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n"
            try
            {
                LoeLog.d(linkInfo + JSONObject(result).toString(4))
            } catch (e: Exception)
            {
                LoeLog.d(linkInfo + result)
            }

            clearCountNet++
            clearNet(false)

            lastNetTime = System.currentTimeMillis()
        }
    }

    private var clearCountNet = 0

    fun selectNet(): JSONArray
    {
        return dbNet?.select(max + 30) ?: JSONArray()
    }

    val max = 30

    fun clearNet(isForce: Boolean = true, limit: Boolean = false)
    {
        if (limit) clearCountNet = max + 1
        if (isForce)
        {
            dbNet?.clear()
            clearCountNet = 0
        } else if (clearCountNet > max)
        {
            if (dbNet != null)
            {
                val sql = """
                delete from ${dbNet!!.name} where
                (select count(id) from ${dbNet!!.name} )> $max and
                   id in (select id from ${dbNet!!.name} order by time desc limit
                     (select count(id) from ${dbNet!!.name}) offset $max )
                """.trimIndent()
                dbNet!!.go(sql)
                clearCountNet = 0
            }
        }
    }

    /****************************************** log *****************************************/

    public var lastLogTime = 0L
        private set

    /**
     * log调试信息
     */
    fun d(tag: String?, msg: Any?)
    {
        if (db != null)
        {
            val s = "" + msg
            db?.insert(
                JSONObject()
                    .put("msg", s)
                    .put("type", "d")
                    .put("tag", tag ?: "logger")
            )
            if (msg is JSONObject)
            {
                LoeLog.d(tag, msg.toString(4))
            } else if (msg is JSONArray)
            {
                LoeLog.d(tag, msg.toString(4))
            } else if (s.startsWith("{"))
            {
                try
                {
                    val jsonString = JSONObject(s).toString(4)
                    LoeLog.d(tag, jsonString)
                } catch (e: Exception)
                {
                    LoeLog.d(tag, s)
                }
            } else if (s.startsWith("["))
            {
                try
                {
                    val jsonString = JSONArray(s).toString(4)
                    LoeLog.d(tag, jsonString)
                } catch (e: Exception)
                {
                    LoeLog.d(tag, s)
                }
            } else
            {
                LoeLog.d(tag, s)
            }
            clearCount++
            clear(false)

            lastLogTime = System.currentTimeMillis()
        }
    }

    fun d(msg: Any?)
    {
        d(null, msg)
    }

    /**
     * log调试信息
     */
    fun e(tag: String?, msg: Any?)
    {
        val s = "" + msg
        // log
        LoeLog.e(tag, s)
        if (db != null)
        {
            db?.insert(
                JSONObject()
                    .put("msg", msg)
                    .put("type", "e")
                    .put("tag", tag ?: "logger")
            )
            clearCount++
            clear(false)

            lastLogTime = System.currentTimeMillis()
        }
    }

    fun e(msg: Any?)
    {
        e(null, msg)
    }

    private var clearCount = 0

    fun select(): JSONArray
    {
        return db?.select(max + 30) ?: JSONArray()
    }

    fun clear(isForce: Boolean = true, limit: Boolean = false)
    {
        if (limit) clearCount = max + 1
        if (isForce)
        {
            db?.clear()
            clearCount = 0
        } else if (clearCount > max)
        {
            if (db != null)
            {
                val sql = """
                delete from ${db!!.name} where
                (select count(id) from ${db!!.name} )> $max and
                   id in (select id from ${db!!.name} order by time desc limit
                     (select count(id) from ${db!!.name}) offset $max )
                """.trimIndent()
                db!!.go(sql)
                clearCount = 0
            }
        }
    }

    /***************************** 环境切换 *****************************/

    var environmentServeType: String
        get() = LoggerSharedManager.getString("logger:environmentServeType")
        set(value)
        {
            LoggerSharedManager.putString("logger:environmentServeType", value)
        }

    var environmentServeBaseUrl: String
        get() = LoggerSharedManager.getString("logger:environmentServeBaseUrl")
        set(value)
        {
            LoggerSharedManager.putString("logger:environmentServeBaseUrl", value)
        }

    var environmentWebType: String
        get() = LoggerSharedManager.getString("logger:environmentWebType")
        set(value)
        {
            LoggerSharedManager.putString("logger:environmentWebType", value)
        }

    var environmentWebBaseUrl: String
        get() = LoggerSharedManager.getString("logger:environmentWebBaseUrl")
        set(value)
        {
            LoggerSharedManager.putString("logger:environmentWebBaseUrl", value)
        }

    val staticServeEnvironmentList = ArrayList<EnvironmentBean>()

    var staticWebEnvironmentList = ArrayList<EnvironmentBean>()

    fun addServeEnvironment(type: String, baseUrl: String)
    {
        val bean = EnvironmentBean(type, baseUrl)
        try
        {
            // 默认第一个
            if (staticServeEnvironmentList.isEmpty() && environmentServeType.isEmpty())
            {
                environmentServeType = type
                environmentServeBaseUrl = baseUrl
            }
            // 正式环境
            else if (isRelease)
            {
                if (type.contains("正式") || type.contains("生产"))
                {
                    environmentServeType = type
                    environmentServeBaseUrl = baseUrl
                }
            }
        } catch (e: Exception)
        {
        }
        staticServeEnvironmentList.add(bean)
    }

    internal var onServeSelect: ((bean: EnvironmentBean) -> Unit)? = null

    internal var onWebSelect: ((bean: EnvironmentBean) -> Unit)? = null

    fun setOnServeEnvironmentListener(onEnvironment: (bean: EnvironmentBean) -> Unit)
    {
        onServeSelect = onEnvironment
        if (staticServeEnvironmentList.isNotEmpty())
        {
            try
            {
                onServeSelect?.invoke(EnvironmentBean(environmentServeType, environmentServeBaseUrl))
            } catch (e: Exception)
            {
                onServeSelect?.invoke(EnvironmentBean("", ""))
            }
        }
    }

    fun setOnWebEnvironmentListener(onEnvironment: (bean: EnvironmentBean) -> Unit)
    {
        val bean = EnvironmentBean("自动环境", "（和服务端同步）")
        staticWebEnvironmentList = arrayListOf(bean)
        if (environmentWebType.isEmpty() || isRelease)
        {
            environmentWebType = bean.type
            environmentWebBaseUrl = bean.baseUrl
        }
        onWebSelect = onEnvironment

        if (environmentWebType == bean.type)
        {
            onWebSelect?.invoke(EnvironmentBean(bean.type, environmentServeBaseUrl))
        } else
        {
            onWebSelect?.invoke(EnvironmentBean(environmentWebType, environmentWebBaseUrl))
        }
    }

    internal var onOpenPage: ((activity: Activity, url: String) -> Unit)? = null
        private set

    /** 设置打开页面 */
    fun setOnOpenPage(on: (activity: Activity, url: String) -> Unit)
    {
        onOpenPage = on
    }

    internal var onHttpTestPage: ((activity: Activity) -> Unit)? = null
        private set

    /** 设置打开http测试页面 */
    fun setOnHttpTestPage(on: (activity: Activity) -> Unit)
    {
        onHttpTestPage = on
    }
}

//      private var touchCount = 1
//      private var lastTouchTime = 0L
//      override fun onTouchEvent(ev: MotionEvent)
//      {
//          if (ev.action == MotionEvent.ACTION_DOWN)
//          {
//              if (System.currentTimeMillis() - lastTouchTime < 800)
//              {
//                  touchCount++
//                  if (touchCount == 3 && ev.rawY < px(100))
//                  {
//                      LoeLogger.toLogger(activity)
//                  }
//              } else
//              {
//                  touchCount = 1
//              }
//              lastTouchTime = System.currentTimeMillis()
//          }
//          if (ev.action == MotionEvent.ACTION_MOVE)
//          {
//              touchCount = 0
//          }
//      }
